package cool.houge.pig.infra.controller;

import am.ik.yavi.builder.ValidatorBuilder;
import am.ik.yavi.core.ConstraintViolationsException;
import am.ik.yavi.core.Validator;
import cool.houge.pig.service.register.EmailActivateInput;
import cool.houge.pig.service.register.EmailRegisterInput;
import cool.houge.pig.service.register.RegisterService;
import cool.houge.pig.util.ServerRequestUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

/**
 * 用户注册控制器.
 *
 * @author KK (kzou227@qq.com)
 */
@Component
public class RegisterController {

  private static final Validator<EmailRegisterInput> EMAIL_REGISTER_INPUT_VALIDATOR =
      ValidatorBuilder.<EmailRegisterInput>of()
          .constraint(EmailRegisterInput::getEmail, "email", c -> c.notNull().email())
          .constraint(
              EmailRegisterInput::getPassword,
              "password",
              c -> c.notNull().greaterThanOrEqual(2).lessThanOrEqual(32))
          .build();

  private final RegisterService registerService;

  public RegisterController(RegisterService registerService) {
    this.registerService = registerService;
  }

  /**
   * 邮箱注册.
   *
   * @param request
   * @return
   */
  public Mono<ServerResponse> emailRegister(ServerRequest request) {
    return request
        .bodyToMono(EmailRegisterInput.class)
        .doOnNext(
            input -> {
              // 验证请求参数
              EMAIL_REGISTER_INPUT_VALIDATOR
                  .validate(input)
                  .throwIfInvalid(ConstraintViolationsException::new);
            })
        .flatMap(registerService::register)
        .flatMap(ServerResponse.ok()::bodyValue);
  }

  /**
   * @param request
   * @return
   */
  public Mono<ServerResponse> activateEmail(ServerRequest request) {
    String cipher = ServerRequestUtils.requiredQueryString(request, "cipher");
    var input = new EmailActivateInput().setCipher(cipher);
    return registerService.activate(input).flatMap(ServerResponse.ok()::bodyValue);
  }
}
